/////////////////////////////////////////////////////////////////////////////////////
// vertex programs

struct vert_in
{
	float4 f4Position : ATTR0;
	float4 f4Color    : ATTR1;
	float4 f4Normal   : ATTR2;
};

struct vert_out
{
	float4 f4Position : POSITION;
	float4 f4Color    : COLOR;
	float1 f1FogExp   : TEXCOORD0;
};

vert_out vertex( 
	vert_in vi, 
	uniform float4x4 f44ModelView, 
	uniform float4x4 f44ModelViewProj )
{
	// fog
	//float1 f1FogDensity = -log2(500);
	float1 f1FogDensity = 1.0 / 500.0;
	float3 f3EyePos     = mul(vi.f4Position, f44ModelView).xyz;
	float1 f1FogDist    = length(f3EyePos);

	// output
	vert_out vo;
	vo.f4Position = mul( vi.f4Position, f44ModelViewProj );
	vo.f4Color    = vi.f4Color;
	vo.f1FogExp   = f1FogDist * f1FogDensity;
	return vo;
}

/////////////////////////////////////////////////////////////////////////////////////
// fragment programs

struct frag_in
{
	float4 f4Color  : COLOR;
	float1 f1FogExp : TEXCOORD0;
};

struct frag_out
{
	float4 f4Color : COLOR;
};

frag_out fragment( frag_in fi )
{
	// fragment color
	float4 f4FragColor = fi.f4Color;

	// fog color
	float4 f4FogColor = float4(0.63, 0.76, 0.94, 1.00);

	// fog density
	//float1 f1Fog = exp2(-abs(fi.f1FogExp));
	float1 f1Fog = 1.0 - min(sqrt(fi.f1FogExp), 1.0);

	// output
	frag_out fo;
	fo.f4Color = lerp(f4FogColor, f4FragColor, (float)f1Fog);
	return fo;
}

/////////////////////////////////////////////////////////////////////////////////////
// techniques

float4x4 g_matModelView;
float4x4 g_matModelViewProj;

technique galleon_tech_nvidia
{
	pass galleon_tech_nvidia_pass0
	{
		DepthTestEnable = true;
		CullFaceEnable  = true;

		VertexProgram   = compile gp5vp vertex(g_matModelView, g_matModelViewProj);
		FragmentProgram = compile gp5fp fragment();
	}
}

technique galleon_tech_amd
{
	pass galleon_tech_amd_pass0
	{
		DepthTestEnable = true;
		CullFaceEnable  = true;

		VertexProgram   = compile arbvp1 vertex(g_matModelView, g_matModelViewProj);
		FragmentProgram = compile arbfp1 fragment();
	}
}
